本程序是用51單片機來軟件解碼pt2262編碼,是一個無線服務呼叫器的代碼已經成功的在產品的應用,有LED顯示.
并有原理圖與pcb文件以及完整的代碼提供下載:
http://www.zg4o1577.cn/ziliao/file/37724122PT2272.rar
; ========================================================================================= ; ========================================================================================= ; PT2272 模擬解碼器(接收來自射頻解碼模塊的2262格式串行數據流) ; 管理三位數碼管顯示器 ; 利用AT24C32實現堆棧式掉電緩存保護,通過特殊的清除發射器清除堆棧 ; 顯示器具有兩級亮度變化 ; 具有蜂鳴器,新的編碼收到后,蜂鳴器鳴響2/3次,顯示器高亮,三秒后正常 ; ; CPU: AT89C2051@12MHz ; ; COPYRIGHT yanggt@163.net SEP 9, 2004 ; ========================================================================================= ; ========================================================================================= EESIZE EQU 32768 ;EEPROM容量(32768/16384/8192/4096/2048/1024/512) PWDF EQU 50H ;EEPROM中用于標識歷史記錄有效 MYA0_3 EQU 00010101B ;有效識別碼,不匹配則不響應 MYCLRL EQU 00H ;主控手機編碼值(目前為 0000H) MYCLRH EQU 00H ;根據A4-A11計算得到(00 D7 D6 D5 D4 D3 D2 D1)(D0) BELONT EQU 40 ;聲音鳴響時間 BELOFT EQU 20 ;靜音時間 SCL BIT P3.0 ;AT24C32(4K字節) SDA BIT P3.1 SIGPIN BIT P3.2 ;接收信號入口 BELL BIT P3.3 ;蜂鳴器控制 VSEL BIT P1.0 ;LED亮度選擇,H=高亮度 U0E BIT P3.5 ;個位LED位選 U1E BIT P3.4 ;十位LED位選 U2E BIT P3.7 ;百位LED位選 BELLSW BIT 78H ;蜂鳴器運行期間=1 EEEMPTY BIT 79H ;EEPROM空標志 BELLON BIT 7AH ;通知蜂鳴器鳴響 CODEOK BIT 7BH ;收到的編碼正確 TMK250 BIT 7CH ;250us標志,每250us置位一次 SIGING BIT 7DH ;手機發射信號正在持續=1,無信號=0 LEDHIGH BIT 7EH ;顯示器亮度標志=0:正常;=1:高亮 TOUTMK BIT 7FH ;顯示器降低亮度時間已到=1 RBUF81 DATA 20H ;后8位第一次采樣結果A4-A11 RBUF82 DATA 21H ;后8位第二次采樣結果A4-A11 RBUF44 DATA 22H ;前4位第12次采樣結果A0-A3 SIGPOT DATA 23H ;接收引腳上次電平,直接保存P3口全部內容 SIGMSK EQU 04H ;SIG----P3.2 TCNTL DATA 24H ;定時計數器(4ms時基) TCNTH DATA 25H TMX16 DATA 26H ;16*250=4000us=4ms BELLTM DATA 27H ;鳴響時間 DBUF0 DATA 28H ;個位顯示緩沖區 DBUF1 DATA 29H ;十位 DBUF2 DATA 2AH ;百位 EEPTRL DATA 2BH ;EEPROM當前位置指針 EEPTRH DATA 2CH EEPOL DATA 2DH ;保存清除指針 EEPOH DATA 2EH ; RES2F DATA 2FH ;使用其中的標志位 EEBUF DATA 30H ;30-37H, I2C緩沖區 BELLCNT DATA 38H ;鳴響次數計數器(3/2/1) BELLTMK DATA 39H CODEL DATA 40H ;接收到編碼低位 CODEH DATA 41H ; 高位 CODELK DATA 42H ;保存上一個編碼 CODEHK DATA 43H ; CODE1L DATA 44H CODE1H DATA 45H ; ========================================================================================= ; ========================================================================================= ORG 0000H LJMP START ; ========================================================================================= ; 250us進入一次,每16次(4ms)切換一次顯示位 ; ========================================================================================= ORG 000BH ;定時器0中斷入口,獨占 R7 TM0SUB: SETB TMK250 TM0_4MS:DJNZ TMX16, TM0_E MOV TMX16, #10H JNB BELLSW, TM0_CLY DJNZ BELLTM, TM0_CLY SETB BELLON TM0_CLY:JB TOUTMK, TM0_0 ;每4ms執行一次 DJNZ TCNTL, TM0_0 DJNZ TCNTH, TM0_0 SETB TOUTMK TM0_0: CJNE R7, #0, TM0_1 ;當前顯示位 CLR U2E MOV P1, DBUF0 INC R7 SETB U0E RETI TM0_1: CJNE R7, #1, TM0_2 CLR U0E MOV P1, DBUF1 INC R7 SETB U1E RETI TM0_2: CLR U1E MOV P1, DBUF2 MOV R7, #0 SETB U2E RETI TM0_E: RETI ; ========================================================================================= ; ========================================================================================= START: MOV P1, #00H ;關閉顯示器,正常亮度 CLR BELLON CLR BELL ACALL EECHK ;檢查EEPROM,確定指針,提取其中最后一個歷史記錄號碼 ACALL TOBUF MOV TMX16, #10H ;中斷計數寄存器置初始值16 SETB TOUTMK ;延遲定時器處于停止狀態 CLR U0E CLR U1E CLR U2E MOV R7, #00H ;從第一位開始顯示 MOV TMOD, #12H ;TIMER0, MODE 2, TIMER1, MODE 1 MOV TL0, #06H MOV TH0, #06H ;時間=250us SETB TR0 SETB ET0 SETB EA MOV A, #6-1 ;開機時蜂鳴器自動鳴響 ACALL BELL_S MOV BELLTM, #BELONT-20 ACALL LEDOFF CLR LEDHIGH ;關閉高亮度 MOV SIGPOT, #00H ;假設開始時接收引腳=0 CLR SIGING SETB F0 ;=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=-- MAIN: JNB BELLSW, MAIN_S0 ACALL BELL_M MAIN_S0:JNB LEDHIGH, MAIN_00 ;顯示器普通亮度,不檢查標志 JNB TOUTMK, MAIN_0 ACALL LEDOFF ;顯示器回到正常亮度 CLR LEDHIGH JB EEEMPTY, MAIN_0 ;沒有尚未確認的編碼 AJMP MAIN_01 MAIN_00:JB EEEMPTY, MAIN_0 ;沒有尚未確認的編碼 JNB TOUTMK, MAIN_0 MOV A, #2-1 ACALL BELL_S ;鳴響 MAIN_01:MOV TCNTL, #LOW(5000/4) ;高亮度持續3000ms=3s后恢復 MOV TCNTH, #HIGH(5000/4) CLR TOUTMK MOV BELLTM, #30 MAIN_0: MOV A, P3 ;監視SIG引腳電平變化 XCH A, SIGPOT XRL A, SIGPOT ANL A, #SIGMSK JZ MAIN ;A=0表示引腳電平無變化 SETB F0 ACALL GETCOD ;開始接收,出錯后直接返回 JC MAIN ;接收代碼無效,舍棄。 ACALL FIND JC MAIN ;C=1,表示代碼無效,什么也不發生 MOV CODE1L, CODEL MOV CODE1H, CODEH CLR F0 ACALL GETCOD ;開始接收,出錯后直接返回 SETB F0 JC MAIN ;接收代碼無效,舍棄。 ACALL FIND JC MAIN ;C=1,表示代碼無效,什么也不發生 MOV B, A MOV A, CODE1L XRL A, CODEL JNZ MAIN_0D MOV A, CODE1H XRL A, CODEH JZ MAIN_0C MAIN_0D:MOV CODE1L, CODEL MOV CODE1H, CODEH CLR F0 ACALL GETCOD ;開始接收,出錯后直接返回 SETB F0 JC MAIN ;接收代碼無效,舍棄。 ACALL FIND JC MAIN ;C=1,表示代碼無效,什么也不發生 MOV B, A MOV A, CODE1L XRL A, CODEL JNZ MAIN_E MOV A, CODE1H XRL A, CODEH JNZ MAIN_E MAIN_0C:MOV A, B JNZ MAIN_1 ;A=1:主控手機,轉去退棧 MOV BELLCNT, #4-1 MOV A, CODEL XRL A, CODELK JNZ MAIN_0A MOV A, CODEH XRL A, CODEHK JZ MAIN_0B ;這里可以進行編碼過濾=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- MAIN_0A:MOV BELLCNT, #6-1 ACALL EEPUSH ;其他手機,轉去保存、顯示 ACALL TOBUF MAIN_0B:SETB TOUTMK MOV TCNTL, #LOW(3000/4) ;高亮度持續3000ms=3s后恢復 MOV TCNTH, #HIGH(3000/4) CLR TOUTMK SETB LEDHIGH ;顯示器進入高亮狀態 MOV A, BELLCNT ACALL BELL_S ;鳴響 MOV BELLTM, #BELONT AJMP MAIN MAIN_1: MOV A, CODEL ;核對手機號碼 XRL A, #MYCLRL JNZ MAIN_E MOV A, CODEH XRL A, #MYCLRH JNZ MAIN_E ACALL EEPOP ;執行退棧操作 MAIN_E: AJMP MAIN ; ========================================================================================= ; 主程序結束 ; ========================================================================================= BELL_S: MOV BELLCNT, A SETB BELLSW SETB BELL RET ; ========================================================================================= BELL_M: JBC BELLON, BELLM RET BELLM: MOV A, BELLCNT BELLM0: JNB ACC.0, BELLM1 MOV BELLTM, #BELOFT ;A.0=1,正在鳴響,應該關閉 CLR BELL AJMP BELLM9 BELLM1: MOV BELLTM, #BELONT ;靜音狀態,應該打開 SETB BELL BELLM9: DJNZ BELLCNT, BELLME CLR BELLSW CLR BELL BELLME: RET ; ========================================================================================= LEDOFF: ANL DBUF0, #0FEH ANL DBUF1, #0FEH ANL DBUF2, #0FEH RET ; ========================================================================================= ; ========================================================================================= TM1SET: CLR TR1 ;1,ACALL=2 CLR TF1 ;1 MOV TL1, DPL ;2 MOV TH1, DPH ;2 SETB TR1 ;1 RET ;2, TOTAL=2+1+1+2+2+1+2=11us ; ========================================================================================= ; 接收代碼,收到兩個相同的編碼即認可。 ; 發射結束后接收下一個。 ; ========================================================================================= GETCOD: NOP GETC_S: MOV DPTR, #65535-50000 ;在50ms內搜索至少持續4ms的低電平 [***] ACALL TM1SET GETC_S0:MOV R6, #16 ;16*250us=4000us=4ms GETC_S1:CLR TMK250 GETC_S2:JB TF1, GETC_E ;這里超時認為目前無發射器工作,或上次發射已結束。 JB SIGPIN, GETC_S0 JNB TMK250, GETC_S2 DJNZ R6, GETC_S1 MOV R5, #4*2 ;首先接收A0-A3,共4位,8個采樣點 MOV DPTR, #65535-8000 ;在接下來的8ms內必須出現上升沿 [***] ACALL TM1SET GETC_0: JB TF1, GETC_E ;這里超時認為目前無發射器工作,或上次發射已結束。 JNB SIGPIN, GETC_0 ; JB SIGING, GETC_F ;上次發射尚未結束,直接返回,不接收編碼。 ; AJMP GETC_20 JNB SIGING, GETC_20 ;上次發射尚未結束,直接返回,不接收編碼。 JNB F0, GETC_20 AJMP GETC_F GETC_1P:MOV DPTR, #65535-1250+11+2 ;在接下來的1250us內必須出現低電平 [***] ACALL TM1SET GETC_1: JB TF1, GETC_F ;超時 JB SIGPIN, GETC_1 MOV DPTR, #65535-1250+11+2 ;在接下來的1250us內必須出現上升沿 [***] ACALL TM1SET GETC_2: JB TF1, GETC_F ;超時 JNB SIGPIN, GETC_2 GETC_20:MOV DPTR, #65535-500+11+2 ;固定延遲500us后采樣 ACALL TM1SET JNB TF1, $ MOV C, SIGPIN ;采樣接收信號 MOV A, RBUF44 RLC A MOV RBUF44, A DJNZ R5, GETC_1P ;循環接收4個數據位,進行8次采樣 MOV R5, #8*2 ;接收A4-A11,共8個數據位,16個采樣點 MOV R0, #RBUF81 ;RBUF81存放第一次采樣值 GETC_3P:MOV DPTR, #65535-1250+11+2 ;在接下來的1250us內必須出現低電平 [***] ACALL TM1SET GETC_3: JB TF1, GETC_F ;超時 JB SIGPIN, GETC_3 MOV DPTR, #65535-1250+11+2 ;在接下來的1250us內必須出現上升沿 [***] ACALL TM1SET GETC_4: JB TF1, GETC_F ;超時 JNB SIGPIN, GETC_4 GETC_40:MOV DPTR, #65535-500+11+2 ;固定延遲500us后采樣 ACALL TM1SET JNB TF1, $ MOV C, SIGPIN ;采樣接收信號 MOV A, @R0 RLC A MOV @R0, A XRL 00H, #RBUF81 ;在RBUF81和RBUF82之間切換 XRL 00H, #RBUF82 DJNZ R5, GETC_3P ;循環接收8個數據位,進行16次采樣 SETB SIGING CLR C RET GETC_E: CLR SIGING GETC_F: SETB C RET ; ========================================================================================= ; ========================================================================================= FIND: MOV A, RBUF44 ;分析代碼 CJNE A, #MYA0_3, FIND_E MOV R4, RBUF81 MOV R5, RBUF82 MOV R6, #7 MOV R0, #00H MOV R1, #00H FIND_L: MOV A, R0 ;結果乘以 3 CLR C RLC A MOV B, A MOV A, R1 RLC A XCH A, B ADD A, R0 MOV R0, A MOV A, B ADDC A, R1 MOV R1, A ;結果乘以 3 結束 MOV A, R4 RLC A MOV R4, A ;D7-->C MOV A, R5 RL A MOV R5, A ANL A, #01H ;D7-->A.0 ADDC A, R0 ;A.0+C+R0 MOV R0, A MOV A, R1 ADDC A, #00H MOV R1, A DJNZ R6, FIND_L ;確定A4-A10的編碼結果 CLR A MOV C, RBUF81.0 ;分析代碼,確定是否主控手機 MOV ACC.0, C MOV C, RBUF82.0 ADDC A, #00H ;A=(0,1,2)。A=0:非主控手機;A=1:主控手機;A=2:無效手機 JB ACC.1, FIND_E ;A=2! MOV CODEL, R0 MOV CODEH, R1 CLR C RET ;A=0/1 FIND_E: SETB C RET ; ========================================================================================= ; ========================================================================================= EECHK: MOV EEPTRL, #00H ;0000H記錄不用,因為0000H用于判斷EEPROM是否空 MOV EEPTRH, #00H MOV EEBUF, #00H MOV EEBUF+1, #00H EECHK0: MOV CODEL, EEBUF ;放到編碼緩沖區 MOV CODEH, EEBUF+1 ANL CODEH, #0FH MOV DPL, EEPTRL ;讀取棧底的兩個字節 MOV DPH, EEPTRH INC DPTR INC DPTR ;指向下一個記錄,但是暫時不修改指針 MOV A, DPH ADD A, #HIGH(65536-EESIZE) ;??? JC EECHK9 ;已經檢查完所有記錄空間。 MOV EEPOL, DPL MOV EEPOH, DPH ;暫時保存在這里 MOV R0, #EEBUF MOV B, #02H ACALL I2CD_R MOV A, EEBUF+1 ANL A, #0F0H XRL A, #PWDF JNZ EECHK9 MOV EEPTRL, EEPOL MOV EEPTRH, EEPOH AJMP EECHK0 EECHK9: CLR EEEMPTY ;假設非空 MOV A, EEPTRL ORL A, EEPTRH JNZ EECHKE SETB EEEMPTY ;聲明EEPROM空 EECHKE: RET ; ========================================================================================= ; ========================================================================================= EEPUSH: MOV EEBUF, CODEL ;寫入EEPROM棧,采用實棧頂 MOV EEBUF+1, CODEH ORL EEBUF+1, #PWDF ;標志,50H MOV DPL, EEPTRL MOV DPH, EEPTRH INC DPTR ;每個記錄進入,指針加 2 INC DPTR MOV A, DPH ;進行堆棧溢出檢查 ADD A, #HIGH(65536-EESIZE) JC EEPUSHE ANL DPL, #0FEH MOV EEPTRL, DPL MOV EEPTRH, DPH MOV R0, #EEBUF MOV B, #02H ACALL I2CD_W CLR EEEMPTY ;聲明EEPROM非空 EEPUSHE:RET ; ========================================================================================= ; ========================================================================================= EEPOP: MOV A, EEPTRL ;EEPROM退出操作 ORL A, EEPTRH JZ EEPOPB EEPOP0: MOV EEPOL, EEPTRL MOV EEPOH, EEPTRH CLR C ;指針減 2,指向上一個數據 MOV A, EEPTRL SUBB A, #02H MOV EEPTRL, A MOV A, EEPTRH SUBB A, #00H MOV EEPTRH, A ;指針已經更新 MOV A, EEPTRL ;檢查退出一個記錄后,堆棧是否變空? ORL A, EEPTRH JNZ EEPOP1 MOV CODEL, A MOV CODEH, A SETB EEEMPTY ;聲明EEPROM空 AJMP EEPOP9 EEPOP1: MOV DPL, EEPTRL ;讀取棧頂記錄 MOV DPH, EEPTRH MOV R0, #EEBUF MOV B, #02H ACALL I2CD_R MOV CODEL, EEBUF ;放到編碼緩沖區 MOV CODEH, EEBUF+1 ANL CODEH, #0FH ;屏蔽掉標志 EEPOP9: MOV EEBUF, #00H ;清除剛才已經退棧的記錄 MOV EEBUF+1, #00H MOV DPL, EEPOL MOV DPH, EEPOH MOV R0, #EEBUF MOV B, #02H ACALL I2CD_W ACALL TOBUF ;送到顯示緩沖區 ACALL LEDOFF EEPOPB: MOV A, #2-1 ACALL BELL_S ;鳴響 ; MOV BELLTM, #30 EEPOPE: RET ; ========================================================================================= ; ========================================================================================= TOBUF: MOV A, CODEL ;填寫顯示緩沖區 MOV B, CODEH ;/100 MOV R2, #00H TOBUF_0:CLR C SUBB A, #100 XCH A, B SUBB A, #00H XCH A, B JC TOBUF_8 INC R2 AJMP TOBUF_0 TOBUF_8:ADD A, #100 MOV B, #10 DIV AB MOV DPTR, #FONT MOVC A, @A+DPTR MOV DBUF1, A MOV A, B MOVC A, @A+DPTR MOV DBUF0, A MOV A, R2 MOVC A, @A+DPTR MOV DBUF2, A MOV CODELK, CODEL MOV CODEHK, CODEH RET ; ========================================================================================= ; ========================================================================================= DELAY: PUSH ACC ;延遲時間=A*10ms MOV A, #20 DLY1: PUSH ACC MOV A, #250 DJNZ ACC, $ ;500us POP ACC DJNZ ACC, DLY1 POP ACC DJNZ ACC, DELAY RET ;======= I2C 子程序 ================================================================= ; I2CD_W, I2CD_R ;LAYER 1 ; I2C_O, I2C_I ;LAYER 2 ; I2C_BG, I2C_ED ;LAYER 3 ;======================================================================================== ; 向存儲器寫入幾個字節,最多8個字節。 ; 入口:DPTR 要寫的EEPROM存儲單元地址。 ; R0 指向要寫入字節在RAM的首地址。 ; B 寫入字節個數。 ; 出口:如果 C=1,說明寫出錯。 I2CD_W: ACALL I2C_BG MOV A, #10100000B ;寫命令 ACALL I2C_O JC I2CD_WE ;C=1, 未收到 ACK 位,出錯,不再繼續處理,直接返回 MOV A, DPH ACALL I2C_O JC I2CD_WE MOV A, DPL ACALL I2C_O JC I2CD_WE I2CD_WL:MOV A, @R0 ACALL I2C_O JC I2CD_WE INC R0 DJNZ B, I2CD_WL ACALL I2C_ED CLR C RET I2CD_WE:ACALL I2C_ED SETB C RET ; ========================================================================================= ; 從 EEPROM 讀入幾個字節 ; 入口:DPTR 要讀的存儲單元地址。 ; R0 指向要讀緩沖區在RAM的首地址。 ; B 讀入字節個數。 ; 出口:讀到的內容在緩沖區中,如果 C=1,說明讀出錯。 I2CD_R: ACALL I2C_BG MOV A, #10100000B ;先發送[寫]命令 ACALL I2C_O JC I2CD_RE ;C=1, 未收到 ACK 位,出錯,不再繼續處理,直接返回 MOV A, DPH ;發送地址低位 ACALL I2C_O JC I2CD_RE MOV A, DPL ;發送地址低位 ACALL I2C_O JC I2CD_RE ACALL I2C_BG MOV A, #10100001B ;發送讀命令 ACALL I2C_O JC I2CD_RE I2CD_IB:MOV DPL, #08H ;取得一個字節 SETB SDA I2CD_IL:SETB SCL ;SCL=1 NOP MOV C, SDA ;MCU 采樣 SDA,送到 C 中 RLC A ;C->ACC.0 CLR SCL ;SCL=0 DJNZ DPL, I2CD_IL ;得到的一個字節在 ACC 中 MOV @R0, A INC R0 MOV A, B XRL A, #01H JZ I2CD_GO CLR SDA NOP I2CD_GO:SETB SCL NOP CLR SCL DJNZ B, I2CD_IB ;取得不止一個字節 ACALL I2C_ED CLR C RET I2CD_RE:ACALL I2C_ED SETB C RET ; ========================================================================================= ;向 IIC 總線發送一個字節 I2C_O: PUSH B MOV B, #08H I2C_OLP:RLC A ;ACC.7 -> C MOV SDA, C SETB SCL ;SCL=1 NOP CLR SCL ;SCL=0 DJNZ B, I2C_OLP SETB SDA ;準備接收 ACK 位 SETB SCL ;SCL=1, [SDA=1] NOP MOV C, SDA CLR SCL POP B RET ;C=1, 未收到 ACK 位,出錯, C=0, 收到 ACK 位,正常 ; ========================================================================================= I2C_BG: SETB SCL ;確保SCL=HIGH CLR SDA ;向 IIC 總線發送開始位 NOP CLR SCL RET ; ========================================================================================= I2C_ED: CLR SDA SETB SCL NOP SETB SDA ;向 IIC 總線發送停止位 RET ; ========================================================================================= ;最好顯示000-999=1000個,否則容易造成誤解,這里顯示全部2187個,0-9,A-F,H,L,P,U,Y ; ========================================================================================= FONT: DB 0FDH ;"0" DB 061H ;"1" DB 0DBH ;"2" DB 0F3H ;"3" DB 067H ;"4" DB 0B7H ;"5" DB 0BFH ;"6" DB 0E1H ;"7" DB 0FFH ;"8" DB 0F7H ;"9" DB 0EFH ;"A" DB 03FH ;"B" DB 09DH ;"C" DB 07BH ;"D" DB 09FH ;"E" DB 08FH ;"F" DB 06FH ;"H" DB 071H ;"J" DB 01DH ;"L" DB 0CFH ;"P" DB 07DH ;"U" DB 077H ;"Y" ; ========================================================================================= END